package 多线程;

public class FalseAwakeningExample {
    public static void main(String[] args) throws InterruptedException {
        MyResource resource = new MyResource();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                resource.produce();
            }
        }, "生产者1").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                resource.produce();

            }
        }, "生产者2").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                resource.consume();
            }
        }, "消费者1").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                resource.consume();
            }
        }, "消费者2").start();
    }
}

class MyResource {
    private int product;

    public synchronized void produce() {
        if (product > 10) {
            System.out.println(Thread.currentThread().getName() + " 即将等待 product 已满 " + product);
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 被唤醒 product 已满 " + product);
        }
        product++;
        System.out.println(Thread.currentThread().getName() + " 进货成功 " + product);
        // 每次都唤醒一下???
        notify();
    }

    /**
     * 原因:生产者 消费者 锁的是同一个对象 生产者连续获取到锁 生产者相互唤醒
     * 过程:
     * 消费者1获得锁 消费者1消费 因product=0消费者1等待
     * 消费者2获得锁 消费者2消费 因product=0消费者2等待
     * 生产者1获得锁,生成(product=1),唤醒消费者1
     * 消费者1获得锁(product=1) 消费者1消费(product=0) 唤醒消费者2  消费者1再次消费因(product=0)消费者1wait
     * 消费者2获得锁(product=0) 消费者2消费(product=-1) 唤醒消费者1 消费者2再次消费因(product=-1)消费者2wait
     * 消费者1获得锁(product=-1) 消费者1消费(product=-2) 唤醒消费者2  消费者1再次消费因(product=-2)消费者1wait
     * ...
     */
    public synchronized void consume() {

        if (product <= 0) {
//        while(product<=0){
            System.out.println(Thread.currentThread().getName() + " 即将等待 product 已空 " + product);

            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 被唤醒product " + product);
        }
        product--;
        System.out.println(Thread.currentThread().getName() + "售货成功 " + product);
        // 每次都唤醒一下???
        notify();
    }
}
